#if defined(TB_REFLECTION_REFLECTION_FUNCTION_HPP__) && defined(__TB_IMPLEMENT_MEM_FUNCTION_VARIADICS)

#define __FUN_CONCAT_ACTUAL( A, B ) A##B
#define __FUN_CONCAT( A, B ) __FUN_CONCAT_ACTUAL( A, B )

#if __TB_IS_RAW_FUNCTOR==1
# define TB_VARIADICS_CLASS_NAME __FUN_CONCAT(__TB_VARIADICS_CLASS_PREFIX, RawFuntionImpl)
#else
# define TB_VARIADICS_CLASS_NAME __FUN_CONCAT(__TB_VARIADICS_CLASS_PREFIX, MemFuntionImpl)
#endif

template <class ClassType, class RetType __TB_PARAM_LIST>
struct TB_VARIADICS_CLASS_NAME : public Function {
  typedef ClassType class_type;

#if __TB_IS_RAW_FUNCTOR==1
  typedef RetType (*FunctorType)(__TB_PASS_PARAM_LIST);
#else
  typedef RetType (ClassType::*FunctorType)(__TB_PASS_PARAM_LIST);
#endif

  __TB_TYPEDEF_TYPES_BLOCK

  TB_VARIADICS_CLASS_NAME(FunctorType func, const TCHAR* name, const TCHAR* param, const TCHAR* prototype)
  : Function(name, param, prototype) {
    func_.func = func;
  }

  uint32 GetArgCount() const OVERRITE {
    return __TB_PARAM_COUNT;
  }

  uint32 GetRetType() const OVERRITE {
    return GetVariantTypeId<RetType>();
  }

  uint32 GetArgType(uint8 argIdx) const OVERRITE {
#ifndef __TB_NO_CASE
    switch (argIdx) {
      __TB_GET_PARAM_TYPE_CASES
    }
#endif
    return 0;
  }

#if __TB_IS_RAW_FUNCTOR==1
  template <typename WithRet = void>
  Variant InvokeWithRetImpl(const std::stack<Variant>& params) const {
    std::stack<Variant> params_ = params;
    __TB_POP_PARAMS_BLOCK
    return Variant::FromValue((func_)(__TB_RETRIVE_PARAM_VALUE_LIST));
  }

  template <>
  typename boost::enable_if<is_void<RetType>, Variant>::type
    InvokeWithRetImpl(const std::stack<Variant>& params) const {
    InvokeWithoutRet(params);
    return Variant();
  }

  Variant InvokeWithRet(const std::stack<Variant>& params) const OVERRITE {
    return InvokeWithRetImpl(params);
  }

  void InvokeWithoutRet(const std::stack<Variant>& params) const OVERRITE {
    std::stack<Variant> params_ = params;
    __TB_POP_PARAMS_BLOCK
    func_.func(__TB_RETRIVE_PARAM_VALUE_LIST);
  }

  bool IsMemberFunction() const OVERRITE { return false; }

#else

  template <typename WithRet=void>
  Variant InvokeWithRetImpl(const std::stack<Variant>& params) const {
    std::stack<Variant> params_ = params;
    __TB_POP_PARAMS_BLOCK
    return Variant::FromValue(((static_cast<class_type*>(obj_))->*func_)(__TB_RETRIVE_PARAM_VALUE_LIST));
  }

  template <>
  typename boost::enable_if<is_void<RetType>, Variant>::type
  InvokeWithRetImpl(const std::stack<Variant>& params) const {
    InvokeWithoutRet(params);
    return Variant();
  }

  Variant InvokeWithRet(const std::stack<Variant>& params) const OVERRITE {
    return InvokeWithRetImpl(params);
  }

  void InvokeWithoutRet(const std::stack<Variant>& params) const OVERRITE {
    std::stack<Variant> params_ = params;
    __TB_POP_PARAMS_BLOCK
    ((static_cast<class_type*>(obj_))->*func_.func)(__TB_RETRIVE_PARAM_VALUE_LIST);
  }

  bool IsMemberFunction() const OVERRITE { return true; }

  mutable void* obj_;

  void BindObject(void* obj) const OVERRITE  { obj_ = obj; }

#endif

  virtual const void *GetFunctorData() const OVERRITE  { return func_.ptr; };

private:
  union FunctionData {
    void *ptr;
    FunctorType func;
  } func_;
};

#if __TB_IS_RAW_FUNCTOR==1
template <typename RetType __TB_PARAM_LIST>
Function* MakeRawFunction(RetType (*fn)(__TB_PASS_PARAM_LIST), const TCHAR* name, const TCHAR* param) {
  return new TB_VARIADICS_CLASS_NAME<NoneType, RetType __TB_PASS_PARAM_LIST_WITH_COMMA>(fn, name, param, "");
}
#else
template <typename ClassType, typename RetType __TB_PARAM_LIST>
Function* MakeMemFunction(RetType (ClassType::*fn)(__TB_PASS_PARAM_LIST), const TCHAR* name, const TCHAR* param) {
  return new TB_VARIADICS_CLASS_NAME<ClassType, RetType __TB_PASS_PARAM_LIST_WITH_COMMA>(fn, name, param, _T(""));
}
#endif

#undef TB_VARIADICS_CLASS_NAME

#undef __FUN_CONCAT_ACTUAL
#undef __FUN_CONCAT

#else
# error "this file can only be included by the function.hpp"
#endif